# -*- coding: UTF-8 -*-

import unittest

from model.gamestate import *
from quick_game_settings import QuickGameSettings
from presenter_mock import PresenterMock
from constants import BOUNDS


class SysSettingsMock:
    def __init__(self, *args):
        self.quick_game = QuickGameMock(*args)


class QuickGameMock:
    def __init__(self, def_time_sec, def_words_per_player, def_players):
        self.def_time_sec = def_time_sec
        self.def_words_per_player = def_words_per_player
        self.def_players = def_players


class QuickGameSettingsTest(unittest.TestCase):
    def setUp(self):
        self.settings = SysSettingsMock(13, 17, 7)
        self.gamestate = GameState(None, None, None,
                                   Phase.QUICK_GAME_SETTINGS, None, None, None)
        self.presenter = PresenterMock(Phase.WELCOME)
        self.presenter.settings = self.settings

    def test_load_defaults(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        self.assertEqual(screen.PROPS['time'].prop, 13)
        self.assertEqual(screen.PROPS['words'].prop, 17)
        self.assertEqual(screen.PROPS['players'].prop, 7)

    @unittest.expectedFailure  # till issue 131 fix
    def test_load_gamestate(self):
        self.gamestate.settings = Settings(time_per_round_sec=7,
                                           words_number=13)
        screen = QuickGameSettings(self.gamestate, self.presenter)
        self.assertEqual(screen.PROPS['time'].prop, 7)
        self.assertEqual(screen.PROPS['words'].prop, 13)
        self.assertEqual(screen.PROPS['players'].prop, 7)

    def test_create_game(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        self.presenter.new_phase = Phase.EDIT_PLAYERS
        screen.next_view()
        self.assertIsInstance(self.gamestate.hat, Hat)
        self.assertEqual(len(self.gamestate.hat.words), 7*17)
        self.assertEqual(len(self.gamestate.players.players), 7)
        for player in self.gamestate.players.players:
            self.assertEqual(len(player.words), 17)
        self.assertEqual(self.gamestate.settings.words_number, 17)
        self.assertEqual(self.gamestate.settings.time_per_round_sec, 13)
        self.assertIsInstance(self.gamestate.players.players_select_strategy,
                              OddStrategy)
        self.assertTrue(self.presenter.is_phase_changed)

    def test_selecting_odd_strategy(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        self.presenter.new_phase = Phase.EDIT_PLAYERS
        screen.next_view()
        self.assertIsInstance(self.gamestate.players.players_select_strategy,
                              OddStrategy)

    def test_selecting_traditional_strategy(self):
        self.presenter.settings.quick_game.def_players = 16
        screen = QuickGameSettings(self.gamestate, self.presenter)
        self.presenter.new_phase = Phase.EDIT_PLAYERS
        screen.next_view()
        self.assertIsInstance(self.gamestate.players.players_select_strategy,
                              TraditionalStrategy)

    def test_go_back(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        screen.go_back()
        self.assertTrue(self.presenter.is_phase_changed)

    def test_reading_properties(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        screen.PROPS['time'].inp.focus = True
        screen.PROPS['time'].inp.text = '245'
        screen.PROPS['time'].inp.focus = False
        screen.PROPS['words'].inp.focus = True
        screen.PROPS['words'].inp.text = '57'
        screen.PROPS['words'].inp.focus = False
        screen.PROPS['players'].inp.focus = True
        screen.PROPS['players'].inp.text = '7'
        screen.PROPS['players'].inp.focus = False
        self.assertEqual(screen.PROPS['time'].prop, 245)
        self.assertEqual(screen.PROPS['words'].prop, 57)
        self.assertEqual(screen.PROPS['players'].prop, 7)

    def test_change_properties(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        for i in range(5):
            screen.PROPS['time'].plus_btn.dispatch('on_release')
        for i in range(3):
            screen.PROPS['time'].minus_btn.dispatch('on_release')
        for i in range(5):
            screen.PROPS['words'].plus_btn.dispatch('on_release')
        for i in range(7):
            screen.PROPS['words'].minus_btn.dispatch('on_release')
        for i in range(6):
            screen.PROPS['players'].plus_btn.dispatch('on_release')
        for i in range(4):
            screen.PROPS['players'].minus_btn.dispatch('on_release')
        self.assertEqual(screen.PROPS['time'].prop, 23)
        self.assertEqual(screen.PROPS['words'].prop, 15)
        self.assertEqual(screen.PROPS['players'].prop, 9)

    def test_bounds(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        for i in range(10):
            screen.PROPS['time'].minus_btn.dispatch('on_release')
        self.assertEqual(screen.PROPS['time'].prop, 5)
        screen.PROPS['time'].inp.focus = True
        screen.PROPS['time'].inp.text = str(BOUNDS['time'][1]+10)
        screen.PROPS['time'].inp.focus = False
        self.assertEqual(screen.PROPS['time'].prop, BOUNDS['time'][1])
        for i in range(57):
            screen.PROPS['words'].plus_btn.dispatch('on_release')
        self.assertEqual(screen.PROPS['words'].prop, 60)
        screen.PROPS['words'].inp.focus = True
        screen.PROPS['words'].inp.text = '0'
        screen.PROPS['words'].inp.focus = False
        self.assertEqual(screen.PROPS['words'].prop, BOUNDS['words'][0])

    def test_invalid_input(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        self.assertEqual(screen.PROPS['time'].prop, 13)
        screen.PROPS['time'].inp.focus = True
        screen.PROPS['time'].inp.text = 'abracadabra'
        screen.PROPS['time'].inp.focus = False
        self.assertEqual(screen.PROPS['time'].prop, 13)

    def test_keyboard_translations(self):
        screen = QuickGameSettings(self.gamestate, self.presenter)
        self.presenter.new_phase = Phase.EDIT_PLAYERS
        screen.PROPS['time'].inp.focus = True
        self.assertTrue(screen.PROPS['time'].inp.focus)
        self.assertFalse(screen.PROPS['words'].inp.focus)
        screen.PROPS['time'].inp.dispatch('on_text_validate')
        self.assertTrue(screen.PROPS['words'].inp.focus)
        screen.PROPS['words'].inp.dispatch('on_text_validate')
        self.assertTrue(screen.PROPS['players'].inp.focus)
        screen.PROPS['players'].inp.dispatch('on_text_validate')
        self.assertTrue(self.presenter.is_phase_changed)


if __name__ == '__main__':
    from kivy.lang import Builder
    import os
    import gettext
    Builder.load_file('ui/quick_game_settings.kv')
    PATH = os.path.abspath('.')
    LOCALE_PATH = os.path.join(PATH, 'locales')
    gettext.bindtextdomain('thehat', LOCALE_PATH)
    lang = gettext.translation('thehat', LOCALE_PATH, ['ru_RU'],
                               codeset='utf-8')
    lang.install(True)
    unittest.main()
